/*	--- 使用DOM --- 


因为【XML】是一种【树形结构的文档】, 它有【2种标准的解析API】：

	· DOM：一次性读取XML, 并在【内存】中表示为【树形结构】;
	· SAX：以【流】的形式读取XML, 使用【事件回调】。


我们先来看如何使用【DOM】来读取【XML】。

【DOM】是【Document Object Model】的缩写, 【DOM模型】就是把【XML结构】作为一个【树形结构处理】, 从【根节点】开始, 每个节点都可以包含任意个子节点。


我们以下面的XML为例：
	
	<?xml version="1.0" encoding="UTF-8" ?>
	<book id="1">
	    <name>Java核心技术</name>
	    <author>Cay S. Horstmann</author>
	    <isbn lang="CN">1234567</isbn>
	    <tags>
	        <tag>Java</tag>
	        <tag>Network</tag>
	    </tags>
	    <pubDate/>
	</book>



如果解析为DOM结构, 它大概长这样：

                      ┌─────────┐
                      │document │
                      └─────────┘
                           │
                           ▼
                      ┌─────────┐
                      │  book   │
                      └─────────┘
                           │
     ┌──────────┬──────────┼──────────┬──────────┐
     ▼          ▼          ▼          ▼          ▼
┌─────────┐┌─────────┐┌─────────┐┌─────────┐┌─────────┐
│  name   ││ author  ││  isbn   ││  tags   ││ pubDate │
└─────────┘└─────────┘└─────────┘└─────────┘└─────────┘
                                      │
                                 ┌────┴────┐
                                 ▼         ▼
                             ┌───────┐ ┌───────┐
                             │  tag  │ │  tag  │
                             └───────┘ └───────┘



注意到最顶层的document代表XML文档, 它是真正的“根”, 而<book>虽然是根元素, 但它是document的一个子节点。


Java提供了DOM API来解析XML, 它使用下面的对象来表示XML的内容：

	· Document：代表整个XML文档;
	· Element：代表一个XML元素;
	· Attribute：代表一个元素的某个属性。



使用DOM API解析一个XML文档的代码如下：*/
InputStream input = Main.class.getResourceAsStream("/book.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(input); 
	// DocumentBuilder.parse(InputStream);
	
	// DocumentBuilderFactory -> DocumentBuilder -> Document


/*
【DocumentBuilder.parse()】用于解析一个XML, 它可以接收【InputStream, File或者URL】, 如果解析无误, 我们将获得【一个Document对象】, 这个对象代表了【整个XML文档的树形结构】, 需要【遍历】以便读取【指定元素的值】：*/
void printNode(Node n, int indent) {
    for (int i = 0; i < indent; i++) {
        System.out.print(' ');
    }

    switch (n.getNodeType()) {
    case Node.DOCUMENT_NODE: // Document节点
        System.out.println("Document: " + n.getNodeName());
        break;
    case Node.ELEMENT_NODE: // 元素节点
        System.out.println("Element: " + n.getNodeName());
        break;
    case Node.TEXT_NODE: // 文本
        System.out.println("Text: " + n.getNodeName() + " = " + n.getNodeValue());
        break;
    case Node.ATTRIBUTE_NODE: // 属性
        System.out.println("Attr: " + n.getNodeName() + " = " + n.getNodeValue());
        break;
    default: // 其他
        System.out.println("NodeType: " + n.getNodeType() + ", NodeName: " + n.getNodeName());
    }

    // 处理层级关系的for循环
    // 	先获取当前Node的FirstChild; 检测FirstChild!=null; child指向同树层的下一个子节点(同权重)
    for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
    	// Sibling  n.  兄弟姐妹/同级
        printNode(child, indent + 1); // indent n. 缩进
    }
}



/*
解析结构如下：

	Document: #document
	 Element: book
	  Text: #text = 
	    
	  Element: name
	   Text: #text = Java核心技术
	  Text: #text = 
	    
	  Element: author
	   Text: #text = Cay S. Horstmann
	  Text: #text = 
	  ...


对于【DOM API】解析出来的结构, 我们从【根节点 Document】出发, 可以遍历所有子节点, 获取所有【元素、属性、文本数据, 还可以包括注释】, 这些节点被统称为【Node】, 每个【Node】都有自己的【Type】, 根据【Type】来区分一个Node到底是【元素, 还是属性, 还是文本, 等等】。


使用【DOM API】时, 如果要读取【某个元素的文本】, 需要访问它的【Text类型的子节点】, 所以使用起来还是【比较繁琐】的。




=====================================================



#	----- 使用DOM の 小结 ----- 


1. Java提供的DOM API可以将XML解析为DOM结构, 以Document对象表示;

2. DOM可在内存中完整表示XML数据结构;

3. DOM解析速度慢, 内存占用大。

4. DOM API中如下表示XML的不同内容：

	· Document：代表整个XML文档;
	· Element：代表一个XML元素;
	· Attribute：代表一个元素的某个属性。

	DocumentBuilderFactory -> DocumentBuilder -> Document

5. XML访问某个元素的子节点, 假设规定了只访问其子节点的某种类型节点, 例如type="Text", 其代码访问相对繁琐。 

*/

